# -*- coding: utf-8 -*-

# 生成器 generator 列表元素可以按照某种算法推算出来，一边循环一边计算的机制，称为生成器

# 方法一 将列表生成式的[]改为()
a_generator = (x * x for x in range(10))
print(a_generator)

# 获取generator的元素
print(next(a_generator))

# generator也是可迭代对象
for x in a_generator:
    print(x, end=' ')
print()


def fib(number):
    n, a, b = 0, 0, 1
    while n < number:
        print(b)
        a, b = b, a + b
        n = n + 1
    return 'done'


print(fib(3))


# 方法二 通过yield
print("方法二")


def fib2(number):
    n, a, b = 0, 0, 1
    while n < number:
        yield b
        a, b = b, a + b
        n = n + 1
# generator和函数的执行流程不一样。函数是顺序执行，遇到return语句或者最后一行函数语句就返回。
# 而变成generator的函数，在每次调用next()的时候执行，遇到yield语句返回，再次执行时从上次返回的yield语句处继续执行
for x in fib2(6):
    print(x, end=' ')
print()

# 用for循环调用generator时，发现拿不到generator的return语句的返回值。
# 如果想要拿到返回值，必须捕获StopIteration错误，返回值包含在StopIteration的value中


def triangles(rows):
    """
    杨辉三角
            1
          1   1
         1  2  1

    """
    next_list = [1]
    n = 0
    while n < rows:
        yield next_list
        next_list.append(0)
        next_list = [next_list[col - 1] + next_list[col] for col in range(len(next_list))]
        n = n + 1


print("杨辉三角: ")
for i in triangles(3):
    print(i)

# for循环的对象都是Iterable类型；
# 凡是可作用于next()函数的对象都是Iterator类型，它们表示一个惰性计算的序列
